
package com.idealighter.game.games.weishuwu.manager;

import com.alibaba.fastjson.TypeReference;

import com.google.common.collect.Lists;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import com.idealighter.game.core.common.Game;
import com.idealighter.game.core.tuple.Pair;
import com.idealighter.game.dictionary.dic.WeishuwuRoomDic;
import com.idealighter.game.dictionary.domain.WeishuwuRoomDomain;
import com.idealighter.game.games.weishuwu.struct.BettingDecision;
import com.idealighter.game.games.weishuwu.struct.WeishuwuCard;
import com.idealighter.game.games.weishuwu.struct.WeishuwuCardsType;
import com.idealighter.game.games.weishuwu.struct.WeishuwuTable;
import com.idealighter.game.games.weishuwu.util.CardsTypeGetter;
import com.idealighter.game.prizepool.manager.RoomPrizePoolMgrScript;
import com.idealighter.game.prizepool.struct.control.WeishuwuControl;
import com.idealighter.game.prizepool.struct.room.ControlStrategy;
import com.idealighter.game.prizepool.struct.room.RoomPrizePool;
import com.idealighter.utils.code.RandCodeUtil;

import java.util.Collections;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 魏蜀吴控制 .
 */
@Singleton
public class WeishuwuControlScript {

  private static final Logger LOG = LoggerFactory.getLogger(WeishuwuControlScript.class);

  private static final TypeReference<WeishuwuControl> WEISHUWU_CONTROL_TYPE =
      new TypeReference<WeishuwuControl>() {};

  @Inject
  private WeishuwuRoomDic roomDic;
  @Inject
  private RoomPrizePoolMgrScript roomPrizePoolMgr;

  /**
   * 控制玩家发牌,玩家和机器人玩才控制 .
   * 
   * @param table .
   */
  public void controlDealCards(WeishuwuTable table) {
    RoomPrizePool roomPrizePool =
        roomPrizePoolMgr.defaultRoomPrizePool(Game.WEISHUWU, table.room.getId());
    boolean controlSeatWin;
    ControlStrategy strategy = null;
    if (roomPrizePool != null) {
      // 房间奖池控制策略
      if (table.tempGold == 0) {
        strategy = roomPrizePool.abledControlStrategy();
        table.tempGold += roomPrizePool.getPrize().get();
      } else {
        strategy = roomPrizePool.abledControlStrategy(table.tempGold);
      }
    }

    // 是否是系统坐庄
    boolean isSys = table.banker().getPlayerId() > 0 ? false : true;

    WeishuwuControl control = null;
    if (strategy != null) {
      control = strategy.control(WEISHUWU_CONTROL_TYPE);
    }

    long totalBet = isSys ? table.playerTotalBets() : table.robotTotalBets();

    boolean win;

    /**
     * step1 . 判断大小
     */
    controlSeatWin = control != null ? RandCodeUtil
        .random(control.getLoseRatio() + control.getWinRatio()) >= control.getLoseRatio()
        : RandCodeUtil.randomBoolean();

    win = RandCodeUtil.randomBoolean();

    // 大牛小马判断
    BettingDecision sb = win ? BettingDecision.DA_NIU : BettingDecision.XIAO_MA;
    BettingDecision otherSb = !win ? BettingDecision.DA_NIU : BettingDecision.XIAO_MA;

    // 该区域是否有人下注
    // 大小马下注

    if (controlSeatWin) {
      if (isSys
          ? table.playerareaBets(sb.type) * table.cbMultiple[sb.type]
              - table.playerareaBets(otherSb.type) * table.cbMultiple[otherSb.type] < 0
          : table.robotareaBets(sb.type) * table.cbMultiple[sb.type]
              - table.robotareaBets(otherSb.type) * table.cbMultiple[otherSb.type] < 0) {

        //
      } else {
        sb = otherSb;
      }

    } else {
      if (isSys
          ? table.playerareaBets(sb.type) * table.cbMultiple[sb.type]
              - table.playerareaBets(otherSb.type) * table.cbMultiple[otherSb.type] > 0
          : table.robotareaBets(sb.type) * table.cbMultiple[sb.type]
              - table.robotareaBets(otherSb.type) * table.cbMultiple[otherSb.type] > 0) {
        //
      } else {
        sb = otherSb;
      }
    }

    long daXiaoMaChips = (long) (isSys ? table.playerareaBets(sb.type) * table.cbMultiple[sb.type]
        : table.robotareaBets(sb.type) * table.cbMultiple[sb.type]);


    /**
     * step3 . 吴蜀判断
     */

    controlSeatWin = control != null ? RandCodeUtil
        .random(control.getLoseRatio() + control.getWinRatio()) >= control.getLoseRatio()
        : RandCodeUtil.randomBoolean();

    long total = isSys
        ? table.playerareaBets(BettingDecision.WU.type)
            + table.playerareaBets(BettingDecision.SHU.type)
            + table.playerareaBets(BettingDecision.WEI.type)
        : table.robotareaBets(BettingDecision.WU.type)
            + table.robotareaBets(BettingDecision.SHU.type)
            + table.robotareaBets(BettingDecision.WEI.type);

    controlSeatWin = isSys ? controlSeatWin : !controlSeatWin;
    BettingDecision wsw = null;
    for (int i = 0; i <= 100000; i++) {
      wsw = randResult();
      double multi = table.cbMultiple[wsw.type] + 2;
      if ((isSys ? table.playerareaBets(wsw.type) * multi > total
          : table.robotareaBets(wsw.type) * multi > total) && !controlSeatWin) {
        break;
      }
      if ((isSys ? table.playerareaBets(wsw.type) * multi < total
          : table.robotareaBets(wsw.type) * multi < total) && controlSeatWin) {
        break;
      }

      if ((isSys ? table.playerareaBets(wsw.type) * multi == total
          : table.robotareaBets(wsw.type) * multi == total)) {
        break;
      }
    }

    BettingDecision shujiangDudu = null;

    if (wsw == BettingDecision.WU) {
      shujiangDudu = BettingDecision.WU_DU_DU;

    } else if (wsw == BettingDecision.SHU) {
      shujiangDudu = BettingDecision.SHU_HU_JIANG;
    }

    long shujiangDuduchips = 0;
    long wswChips = (long) (isSys ? table.playerareaBets(wsw.type) * table.cbMultiple[wsw.type]
        : table.robotareaBets(wsw.type) * table.cbMultiple[wsw.type]);
    if (shujiangDudu != null) {
      shujiangDuduchips = (long) (isSys
          ? table.playerareaBets(shujiangDudu.type) * table.cbMultiple[shujiangDudu.type]
          : table.robotareaBets(shujiangDudu.type) * table.cbMultiple[shujiangDudu.type]);
      if (shujiangDuduchips > 0 && controlSeatWin) {
        if (wswChips + shujiangDuduchips + daXiaoMaChips > totalBet) {
          shujiangDudu = null;
        }
      } else {
        if (shujiangDuduchips > 0) {
          // shujiangDudu = RandCodeUtil.randomBoolean() ? null :
          // shujiangDudu;
        }
      }
    }
    long wuPaireChps = (long) (isSys
        ? table.playerareaBets(BettingDecision.WU_PAIRE.type)
            * table.cbMultiple[BettingDecision.WU_PAIRE.type]
        : table.robotareaBets(BettingDecision.WU_PAIRE.type)
            * table.cbMultiple[BettingDecision.WU_PAIRE.type]);
    long shuPaireChps = (long) (isSys
        ? table.playerareaBets(BettingDecision.SHU_PAIRE.type)
            * table.cbMultiple[BettingDecision.SHU_PAIRE.type]
        : table.robotareaBets(BettingDecision.SHU_PAIRE.type)
            * table.cbMultiple[BettingDecision.SHU_PAIRE.type]);
    BettingDecision shuPaire = null;
    BettingDecision wuPaire = null;
    if (wuPaireChps > 0 && controlSeatWin) {
      if (wswChips + shujiangDuduchips + wuPaireChps + daXiaoMaChips < total) {
        wuPaire = BettingDecision.WU_PAIRE;
      }

    } else {
      if (wuPaireChps > 0) {
        wuPaire = BettingDecision.WU_PAIRE;
      }
      // wuPaire = RandCodeUtil.randomBoolean() ? null :
      // BettingDecision.WU_PAIRE;
    }

    if (shuPaireChps > 0 && controlSeatWin) {
      if (wswChips + shujiangDuduchips + shuPaireChps + wuPaireChps + daXiaoMaChips < total) {
        shuPaire = BettingDecision.SHU_PAIRE;
      }
    } else {
      if (shuPaireChps > 0) {
        shuPaire = BettingDecision.SHU_PAIRE;
      }

      // shuPaire = RandCodeUtil.randomBoolean() ? null :
      // BettingDecision.SHU_PAIRE;
    }
    findCard(table, wsw, shujiangDudu, sb, wuPaire, shuPaire);
  }

  /**
   * 发牌 .
   * 
   * 
   * @param table .
   */
  public void dealCards(WeishuwuTable table) {
    int cardIndex = table.cardIndex;
    /**
     * 先发两张手牌 .
     */
    if (cardIndex + 12 > table.cards.size()) {
      cardIndex = 0;
    }
    List<WeishuwuCard> cards1 = Lists.newArrayList();
    List<WeishuwuCard> cards2 = Lists.newArrayList();
    cards1.addAll(table.cards.subList(cardIndex, cardIndex += 2));
    cards2.addAll(table.cards.subList(cardIndex, cardIndex += 2));
    int normalPoint = CardsTypeGetter.getCardPoint(cards1);
    int bankerPoint = CardsTypeGetter.getCardPoint(cards2);
    // 闲家补牌
    if (normalPoint <= 5 && bankerPoint < 8) {
      WeishuwuCard weishuWutCardPlayer = table.cards.get(cardIndex);
      cards1.add(weishuWutCardPlayer);
      cardIndex += 1;
    }
    // 庄家补牌
    normalPoint = CardsTypeGetter.getCardPoint(cards1);
    WeishuwuCard weishuwuCardBanker = table.cards.get(cardIndex);
    if (normalPoint < 8 && bankerPoint < 8) {
      switch (bankerPoint) {
        case 0:
          cards2.add(weishuwuCardBanker);
          break;
        case 1:
          cards2.add(weishuwuCardBanker);
          break;
        case 2:
          cards2.add(weishuwuCardBanker);
          break;
        case 3:
          if (normalPoint != 8) {
            cards2.add(weishuwuCardBanker);
          }
          break;
        case 4:
          if (normalPoint != 1 && normalPoint != 8 && normalPoint != 9 && normalPoint != 0) {
            cards2.add(weishuwuCardBanker);
          }
          break;
        case 5:
          if (normalPoint != 1 && normalPoint != 2 && normalPoint != 3 && normalPoint != 8
              && normalPoint != 9 && normalPoint != 0) {
            cards2.add(weishuwuCardBanker);
          }
          break;
        case 6:
          if (normalPoint == 6 || normalPoint == 7) {
            cards2.add(weishuwuCardBanker);
          }
          break;
        case 7:
          break;
        case 8:
          break;
        case 9:
          break;

        default:
          break;
      }

    }
    table.cardIndex += cards1.size() + cards2.size();
    table.normalPlayer.addAll(cards1);
    table.banker.addAll(cards2);
    LOG.info("魏蜀吴游戏[{}]开始发牌", table.getId());

  }

  /**
   * 结算房间奖池 .
   *
   * @param table .
   */
  public void balanceControl(WeishuwuTable table) {
    long gold = convertGold(table.room.getId().intValue(), table.earn);
    RoomPrizePool seatRoomPrizePool =
        roomPrizePoolMgr.defaultRoomPrizePool(Game.WEISHUWU, table.room.getId());
    if (seatRoomPrizePool != null) {
      long prize = seatRoomPrizePool.getPrize().get();
      prize += gold;
      seatRoomPrizePool.getPrize().getAndSet(prize);
    }
  }

  /**
   * 筹码换算金币,只会是多个金币等于一个筹码 .
   * 
   * @param roomId .
   * @param chips .
   */
  public long convertGold(int roomId, long chips) {
    WeishuwuRoomDomain roomDomain = roomDic.get(roomId);

    return chips * roomDomain.getProportionGold() / roomDomain.getProportionChips();
  }

  /**
   * .
   * 
   * @param table .
   * @return
   */
  public List<Pair<List<WeishuwuCard>, List<WeishuwuCard>>> createCards(WeishuwuTable table) {
    List<Pair<List<WeishuwuCard>, List<WeishuwuCard>>> cardlist = Lists.newArrayList();

    int cardIndex = 0;
    int num = 100000;
    for (int i = 0; i < num; i++) {
      if (cardIndex >= table.cards.size() - 10) {
        cardIndex = 0;
        Collections.shuffle(table.cards);
      }
      List<WeishuwuCard> shu = Lists.newArrayList();
      List<WeishuwuCard> wu = Lists.newArrayList();
      shu.addAll(table.cards.subList(cardIndex, cardIndex += 2));
      wu.addAll(table.cards.subList(cardIndex, cardIndex += 2));
      int shuPoint = CardsTypeGetter.getCardPoint(shu);
      int wuPoint = CardsTypeGetter.getCardPoint(wu);
      // 蜀补牌
      if (shuPoint <= 5 && wuPoint < 8) {
        WeishuwuCard shu1 = table.cards.get(cardIndex);
        shu.add(shu1);
        cardIndex += 1;
      }
      shuPoint = CardsTypeGetter.getCardPoint(shu);
      // 庄家补牌
      WeishuwuCard weishuwuCardBanker = table.cards.get(cardIndex);
      if (shuPoint < 8 && wuPoint < 8) {

        if (wuPoint < 4) {
          wu.add(weishuwuCardBanker);
        } else if (wuPoint == 4 && shuPoint > 1) {
          wu.add(weishuwuCardBanker);
        }

        switch (wuPoint) {
          case 5:
            if (shuPoint > 3) {
              wu.add(weishuwuCardBanker);
            }
            break;
          case 6:
            if (shuPoint == 6 || shuPoint == 7) {
              wu.add(weishuwuCardBanker);
            }
            break;
          default:
            break;
        }
      }
      cardlist.add(new Pair<List<WeishuwuCard>, List<WeishuwuCard>>(shu, wu));
    }
    return cardlist;
  }

  /**
   * .
   * 
   * @param table .
   * @param wsw .
   * @param duduHujiang .
   * @param daNiuOrXiaoMa .
   * @param wupaire .
   * @param shupaire .
   */
  public void findCard(WeishuwuTable table, BettingDecision wsw, BettingDecision duduHujiang,
      BettingDecision daNiuOrXiaoMa, BettingDecision wupaire, BettingDecision shupaire) {

    Pair<List<WeishuwuCard>, List<WeishuwuCard>> card = null;

    List<Pair<List<WeishuwuCard>, List<WeishuwuCard>>> cardlist = createCards(table);

    for (Pair<List<WeishuwuCard>, List<WeishuwuCard>> li : cardlist) {
      List<WeishuwuCard> shu = li.v1;
      List<WeishuwuCard> wu = li.v2;
      int shuPoint = CardsTypeGetter.getCardPoint(shu);
      int wuPoint = CardsTypeGetter.getCardPoint(wu);

      boolean daNiuAndxiaoMa = shu.size() + wu.size() > 4 ? true : false;

      final boolean shuPaire =
          CardsTypeGetter.getCardsType(shu.subList(0, 2)) == WeishuwuCardsType.PAIR ? true : false;

      final boolean wuPaire =
          CardsTypeGetter.getCardsType(wu.subList(0, 2)) == WeishuwuCardsType.PAIR ? true : false;

      boolean shuwuJiang = shuPoint >= 8 ? true : false;

      boolean wuDudu = wuPoint >= 8 ? true : false;

      BettingDecision re = null;

      if (shuPoint > wuPoint) {
        re = BettingDecision.SHU;
      } else if (shuPoint < wuPoint) {
        re = BettingDecision.WU;
      } else {
        re = BettingDecision.WEI;
      }

      boolean isDaNiuXiaoMa = false;

      if (daNiuOrXiaoMa == BettingDecision.DA_NIU) {
        if (daNiuAndxiaoMa) {
          isDaNiuXiaoMa = true;
        }

      } else if (daNiuOrXiaoMa == BettingDecision.XIAO_MA) {
        if (!daNiuAndxiaoMa) {
          isDaNiuXiaoMa = true;
        }

      }

      boolean isShjAndWdd = false;
      // 不开都督虎将
      if (duduHujiang == null) {
        if (!wuDudu && !shuwuJiang) {
          isShjAndWdd = true;
        }
      } else if ((duduHujiang == BettingDecision.WU_DU_DU && wuDudu)
          || (duduHujiang == BettingDecision.SHU_HU_JIANG && shuwuJiang)) {
        isShjAndWdd = true;
      }

      boolean isShuPare = false;
      if (shupaire == null) {
        if (!shuPaire) {
          isShuPare = true;
        }
      } else if (shupaire == BettingDecision.SHU_PAIRE && shuPaire) {
        isShuPare = true;

      }
      boolean isWupaire = false;
      if (wupaire == null) {
        if (!wuPaire) {
          isWupaire = true;
        }
      } else if (wupaire == BettingDecision.WU_PAIRE && wuPaire) {
        isWupaire = true;
      }

      if (wsw == re && isDaNiuXiaoMa && isShjAndWdd && isShuPare && isWupaire) {
        card = li;
        break;
      }
    }
    if (card == null) {
      dealCards(table);
      return;
    }

    table.normalPlayer.addAll(card.v1);
    table.banker.addAll(card.v2);

    LOG.info("魏蜀吴游戏[{}]开始发牌", table.getId());

  }

  /**
   * 随机结果.
   * 
   * @return
   */
  public BettingDecision randResult() {
    int random = RandCodeUtil.random(1, 17);
    if (random <= 8) {
      return BettingDecision.WU;
    } else if (random <= 16) {
      return BettingDecision.SHU;
    } else {
      return BettingDecision.WEI;
    }
  }

}
